<template>
  <div class="player" v-show="playlist.length">
    <!-- fullScreen 播放器展开或者收缩 -->
    <div class="normal-player" v-show="fullScreen">
      <div class="background">
        <img :src="currentSong.pic">
      </div>
      <div class="top">
        <!-- 收缩按钮 -->
        <div class="back" @click="goBack">
          <i class="icon-back"></i>
        </div>
        <h1 class="title">{{currentSong.name}}</h1>
        <h2 class="subtitle">{{currentSong.singer}}</h2>
      </div>
      <!-- 中间旋转图片 -->
      <div class="middle"
          @touchstart.prevent="onMiddleTouchStart"
          @touchmove.prevent="onMiddleTouchMove"
          @touchend.prevent="onMiddleTouchEnd"
      >
        <div class="middle-l" :style="middleLStyle" >
          <div class="cd-wrapper">
            <div class="cd" ref="cdRef">
              <img ref="cdImageRef" :src="currentSong.pic" :class="cdCls" class="image" alt="">
            </div>
          </div>
          <!-- 当前正在播放的歌词 -->
          <div class="playing-lyric-wrapper">
            <div class="playing-lyric">{{playingLyric}}</div>
          </div>
        </div>
        <!-- 歌词列表 -->
      <scroll class="middle-r" ref="lyricScrollRef"  :style="middleRStyle">
        <div class="lyric-wrapper">
          <div v-if="currentLyric" ref="lyricListRef">
            <p
                class="text"
                :class="{'current': currentLineNum ===index}"
                v-for="(line,index) in currentLyric.lines"
                :key="line.num"
                >
                  {{line.txt}}
                </p>
          </div>
          <!-- 歌曲没有歌词的情况 -->
          <div class="pure-music" v-show="pureMusicLyric">
            <p>{{pureMusicLyric}}</p>
          </div>
        </div>
      </scroll>
      </div>
      <div class="bottom">
        <!-- 歌词显示和图片显示 两个小白点 -->
        <div class="dot-wrapper">
          <span class="dot" :class="{'active':currentShow === 'cd'}"></span>
          <span class="dot" :class="{'active':currentShow === 'lyric'}"></span>
        </div>
        <!-- 进度条 -->
        <div class="progress-wrapper">
          <span class="time time-l">{{formatTime(currentTime)}}</span>
          <div class="progress-bar-wrapper">
            <prigress-bar ref="barRef" :progress="progress" @progress-changing="onProgressChanging" @progress-changed="onProgressChanged"></prigress-bar>
          </div>
          <span class="time time-r">{{formatTime(currentSong.duration)}}</span>
        </div>
        <div class="operators">
          <!-- 播放模式 -->
          <div class="icon i-left">
            <i :class="modeIcon" @click="changeModel"></i>
          </div>
          <div class="icon i-left" :class="disableCls">
            <i @click="prev" class="icon-prev"></i>
          </div>
          <div class="icon i-center" :class="disableCls">
            <i @click="togglePlay" :class="playicon"></i>
          </div>
          <div class="icon i-right" :class="disableCls">
            <i @click="next" class="icon-next"></i>
          </div>
          <!-- 歌曲收藏 -->
          <div class="icon i-right" >
            <i class="icon-not-favorite" :class="getFavoriteIcon(currentSong)" @click="toggleFavorite(currentSong)"></i>
          </div>
        </div>
      </div>
    </div>
    <!-- 底层播放 -->
    <mini-player
      :progress="progress"
      :togglePlay="togglePlay"
    ></mini-player>
    <!-- pause监听歌曲关闭事件 canplay监听歌曲缓存播放触发 timeupdate返回播放时间 -->
    <audio @timeupdate="updateTime" @ended="end" @canplay="ready" ref="audioRef"  @pause="pause" @error="error"></audio>
  </div>
</template>
<script>
import { computed, watch, ref, nextTick } from 'vue'
import { useStore } from 'vuex' // vue3中使用vuex中的数据
import userMode from './use-mode'
import useFavorite from './use-favorite'
import useLyric from './use-lyric'
import useCd from './use-cd'
import useMiddleInteractive from './use-middle-interactive'
import PrigressBar from './progress-bar.vue'
import MiniPlayer from './mini-player'
import { formatTime } from '../../assets/js/util'
import { PLAY_MODE } from '@/assets/js/constant'
import Scroll from '../base/scroll/scroll.vue'

export default {
  name: 'player',
  components: {
    PrigressBar,
    Scroll,
    MiniPlayer
  },
  setup() {
    // state
    const audioRef = ref(null) // 获取播放器的节点操作Dom
    const songReady = ref(false)
    const barRef = ref(null) // 进度条组件Dom
    const currentTime = ref(0) // 当前播放时长
    let progressChanging = false // BUG 来控制歌曲拖动和播放器冲突问题 如果是用户拖动就不修改
    // vuex
    const store = useStore() // vue3 中获取vuex的实例来操作数据
    const fullScreen = computed(() => store.state.fullScreen) // 响应式数据所以用computed 播放器展开收缩状态
    const currentSong = computed(() => store.getters.currentSong) // 从vuex的计算属性中获取当前播放的歌曲
    const playing = computed(() => store.state.playing) // 从vuex中获取到歌曲的状态
    const currentIndex = computed(() => store.state.currentIndex) // 播放歌曲的下标
    const playlist = computed(() => store.state.playlist) // 正在播放的列表
    const playMode = computed(() => store.state.playMode) // 播放模式
    // computed
    const disableCls = computed(() => { // 点击播放和前进后台按钮 添加class
      return songReady.value ? '' : 'disable'
    })
    const playicon = computed(() => { // 播放按钮的icon图片改变
        return playing.value ? 'icon-pause' : 'icon-play'
    })
    const progress = computed(() => { // 已经播放的时间除以 总时间 得到当前播放的时间
      return currentTime.value / currentSong.value.duration
    })
    // hooks 引用use-mode。js
    const { cdCls, cdImageRef, cdRef } = useCd()
    const { modeIcon, changeModel } = userMode()// 播放模式逻辑
    const { getFavoriteIcon, toggleFavorite } = useFavorite() // 收藏歌曲逻辑
    const { currentLyric, currentLineNum, playingLyric, pureMusicLyric, stopLyric, playLyric, lyricScrollRef, lyricListRef } = useLyric({ songReady, currentTime })
    const { currentShow, middleLStyle, middleRStyle, onMiddleTouchStart, onMiddleTouchMove, onMiddleTouchEnd } = useMiddleInteractive()
    // watch
    watch(currentSong, (newSong) => { // 监听歌曲信息改变vuex内容状态
        if (!newSong.id || !newSong.url) {
          return
        }
        currentTime.value = 0 // 进度条改为0
        songReady.value = false
        const audioEl = audioRef.value
        audioEl.src = newSong.url
        audioEl.play()
        store.commit('setPlayingState', true)
      })
      watch(playing, (newPlaying) => { // 监听歌曲的播放状态 改变播放器的状态
        if (!songReady.value) {
          return
        }
        const audioEl = audioRef.value
        if (newPlaying) {
          audioEl.play() // 播放歌曲
          playLyric() // 同步歌词
        } else {
          audioEl.pause() // 暂停歌曲
          stopLyric() // 暂停歌词
        }
      })
      watch(fullScreen, async (newFullScreen) => { // 收缩 展开 播放模式改变
        if (newFullScreen) {
          await nextTick()
          barRef.value.setOffset(progress.value) // 进度条时间定位
        }
      })
      // methods
      function updateTime(e) { // 获取到歌曲播放时长
        if (!progressChanging) { // 不是用户拖动的时候才去修改进度
          currentTime.value = e.target.currentTime
        }
      }
      function pause() { // 歌曲如果关闭的话改变状态
         store.commit('setPlayingState', false)
      }
      function goBack() { // 播放歌曲的收缩
        store.commit('setfullScreen', false)
      }
      function prev() { // 上一首 如果是-1 播放最后一曲歌
        let index = currentIndex.value - 1
        const list = playlist.value
        if (!songReady.value || !list.length) { return }
        if (list.length === 1) { // 如果播放列表就一首歌
          loop()
        } else {
          if (index === -1) {
          index = list.length - 1
          }
          store.commit('setCurrentIndex', index)
          if (!playing.value) { // 如果是歌曲播放是暂停情况 改成播放
            store.commit('setPlayingState', true)
          }
        }
      }
      function next() { // 下一首 如果是播放的是最后一曲歌 下标改为0
         let index = currentIndex.value + 1
        const list = playlist.value
        if (!songReady.value || !list.length) { return }
         if (list.length === 1) { // 如果播放列表就一首歌
          loop()
        } else {
          if (index === list.length) {
          index = 0
          }
          store.commit('setCurrentIndex', index)
          if (!playing.value) {
            store.commit('setPlayingState', true)
          }
        }
      }
       function togglePlay() { // 点击播放暂停按钮
       if (!songReady.value) {
         return
       }
        store.commit('setPlayingState', !playing.value)
      }
      function error() { // 如果歌曲出错
        songReady.value = true
      }
      function loop() { // 循环播放单曲播放
        const audioEl = audioRef.value
        audioEl.currentTime = 0
        audioEl.play()
        // 单选循环播放会触发暂停事件 改变vuex的歌曲状态
        store.commit('setPlayingState', true)// 改变歌曲状态
      }
      function ready() { // 歌曲缓存完成触发事件
        if (songReady.value) { // 异步过程
          return
        }
        songReady.value = true
        playLyric() //  播放歌词
        console.log('歌曲缓存完成触发事件', songReady.value)
      }
      function onProgressChanging(progress) {
        progressChanging = true
        currentTime.value = currentSong.value.duration * progress // 修改歌曲当前播放时间
        // 同步歌词逻辑
        playLyric() // 同步歌词位置
        stopLyric()// 歌词停止播放
      }
      function onProgressChanged(progress) { // 修改真实的歌曲播放时间
        progressChanging = false
        audioRef.value.currentTime = currentTime.value = currentSong.value.duration * progress
        if (!playing.value) { // 如果歌曲暂停改成播放
          store.commit('setPlayingState', true)
        }
        playLyric() // 同步歌词位置
      }
      function end() { // 一首歌曲播放完回调的函数
        currentTime.value = 0
        if (playMode.value === PLAY_MODE.loop) {
          loop() // 循环播放
        } else {
          next()// 下一曲
        }
      }
    return {
      audioRef,
      disableCls,
      currentTime,
      ready,
      pause,
      progress,
      updateTime,
      goBack,
      togglePlay,
      playicon,
      fullScreen,
      currentSong,
      currentIndex,
      playlist,
      barRef,
      next,
      prev,
      error,
      formatTime,
      // use-mode
      modeIcon,
      changeModel,
      // favorite
      getFavoriteIcon,
      toggleFavorite,
      onProgressChanging,
      onProgressChanged,
      end,
      cdCls,
      cdImageRef,
      cdRef,
      // lyric
      currentLyric,
      currentLineNum,
      lyricScrollRef,
      lyricListRef,
      pureMusicLyric,
      playingLyric,
      // miile
      currentShow,
      middleLStyle,
      middleRStyle,
      onMiddleTouchStart,
      onMiddleTouchMove,
      onMiddleTouchEnd
    }
  }
}
</script>
<style lang="scss" scoped>
  .player {
    .normal-player {
      position: fixed;
      left: 0;
      right: 0;
      top: 0;
      bottom: 0;
      z-index: 150;
      background: $color-background;
      .background {
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
        z-index: -1;
        opacity: 0.6;
        filter: blur(20px);

        img {
          width: 100%;
          height: 100%;
        }
      }
      .top {
        position: relative;
        margin-bottom: 25px;
        .back {
          position: absolute;
          top: 0;
          left: 6px;
          z-index: 50;
        }
        .icon-back {
          display: block;
          padding: 9px;
          font-size: $font-size-large-x;
          color: $color-theme;
          transform: rotate(-90deg);
        }
        .title {
          width: 70%;
          margin: 0 auto;
          line-height: 40px;
          text-align: center;
          @include no-wrap();
          font-size: $font-size-large;
          color: $color-text;
        }
        .subtitle {
          line-height: 20px;
          text-align: center;
          font-size: $font-size-medium;
          color: $color-text;
        }
      }
      .middle {
        position: fixed;
        width: 100%;
        top: 80px;
        bottom: 170px;
        white-space: nowrap;
        font-size: 0;
        .middle-l {
          display: inline-block;
          vertical-align: top;
          position: relative;
          width: 100%;
          height: 0;
          padding-top: 80%;
          .cd-wrapper {
            position: absolute;
            left: 10%;
            top: 0;
            width: 80%;
            box-sizing: border-box;
            height: 100%;
            .cd {
              width: 100%;
              height: 100%;
              border-radius: 50%;
              img {
                position: absolute;
                left: 0;
                top: 0;
                width: 100%;
                height: 100%;
                box-sizing: border-box;
                border-radius: 50%;
                border: 10px solid rgba(255, 255, 255, 0.1);
              }
              .playing {
                animation: rotate 20s linear infinite//旋转效果
              }
            }
          }
          .playing-lyric-wrapper {
            width: 80%;
            margin: 30px auto 0 auto;
            overflow: hidden;
            text-align: center;
            .playing-lyric {
              height: 20px;
              line-height: 20px;
              font-size: $font-size-medium;
              color: $color-text-l;
            }
          }
        }
        .middle-r {
          display: inline-block;
          vertical-align: top;
          width: 100%;
          height: 100%;
          overflow: hidden;
          .lyric-wrapper {
            width: 80%;
            margin: 0 auto;
            overflow: hidden;
            text-align: center;
            .text {
              line-height: 32px;
              color: $color-text-l;
              font-size: $font-size-medium;
              &.current {
                color: $color-text;
              }
            }
            .pure-music {
              padding-top: 50%;
              line-height: 32px;
              color: $color-text-l;
              font-size: $font-size-medium;
            }
          }
        }
      }
      .bottom {
        position: absolute;
        bottom: 50px;
        width: 100%;
        .dot-wrapper {
          text-align: center;
          font-size: 0;
          .dot {
            display: inline-block;
            vertical-align: middle;
            margin: 0 4px;
            width: 8px;
            height: 8px;
            border-radius: 50%;
            background: $color-text-l;
            &.active {
              width: 20px;
              border-radius: 5px;
              background: $color-text-ll;
            }
          }
        }
        .progress-wrapper {
          display: flex;
          align-items: center;
          width: 80%;
          margin: 0px auto;
          padding: 10px 0;
          .time {
            color: $color-text;
            font-size: $font-size-small;
            flex: 0 0 40px;
            line-height: 30px;
            width: 40px;
            &.time-l {
              text-align: left;
            }
            &.time-r {
              text-align: right;
            }
          }
          .progress-bar-wrapper {
            flex: 1;
          }
        }
        .operators {
          display: flex;
          align-items: center;
          .icon {
            flex: 1;
            color: $color-theme;
            &.disable {
              color: $color-theme-d;
            }
            i {
              font-size: 30px;
            }
          }
          .i-left {
            text-align: right;
          }
          .i-center {
            padding: 0 20px;
            text-align: center;
            i {
              font-size: 40px;
            }
          }
          .i-right {
            text-align: left
          }
          .icon-favorite {
            color: $color-sub-theme;
          }
        }
      }
      &.normal-enter-active, &.normal-leave-active {
        transition: all .6s;
        .top, .bottom {
          transition: all .6s cubic-bezier(0.45, 0, 0.55, 1);
        }
      }
      &.normal-enter-from, &.normal-leave-to {
        opacity: 0;
        .top {
          transform: translate3d(0, -100px, 0);
        }
        .bottom {
          transform: translate3d(0, 100px, 0)
        }
      }
    }
  }
</style>
